import React, {useCallback, useEffect, useRef, useState} from "react";
import {Select} from "antd";
import {debounce} from "../../utils/httpUtil";

/**
 * 支持大数据量的select包装
 * @param props
 *      debounceTime：防抖动超时时间，默认300；
 *      toManyChildrenNotice：太多可选值的提示，reactNode类型，可使用默认的提示；
 *      maxChildrenLength：最多显示子组件数量
 *      selected：选中的子组件，默认选中过的都会放到可选值里面，如果有别的组件来控制当前组件的可选值，可以接管该值（必须同时接管setSelected），实现手动清除该变量，默认情况下不需要手动接管；
 *      其余属性和antd的select完全一样
 *
 * @returns {*}
 * @constructor
 */
export function SuperSelect(props) {

    const {children, toManyChildrenNotice, maxChildrenLength, debounceTime, ...rest} = props;

    const [filterResult, setFilterResult] = useState({
        children: [],
        overFlow: false,
    });

    const [showChildren, setShowChildren] = useState([]);

    const childrenMap = useRef(new Map());

    const toManyNotice = toManyChildrenNotice || <Select.Option
        key="toManyChildrenNotice"
        value="toManyChildrenNotice"
        disabled={true}
    >内容过多，请搜索来获取更多内容</Select.Option>;

    const searchNow = (value) => {
        // const start = new Date().getTime();
        // let count = 0;
        const childs = React.Children.toArray(children);
        const optionFilterProp = props.optionFilterProp || "value";
        let searchResults = [];
        const maxChildLength = maxChildrenLength || 100;
        let overFlow = false;
        if (value == null || value === "") {
            //没有搜索的时候
            // console.log("没有搜索的时候", children);
            searchResults = childs.slice(0, maxChildLength);
            if (searchResults.length >= maxChildLength) {
                overFlow = true;
            }
        } else {
            //遍历搜索
            for (let i = 0; i < childs.length; i++) {
                const child = childs[i];
                const filterProp = "children" === optionFilterProp ? JSON.stringify(child.props) : JSON.stringify(child.props[optionFilterProp]);
                if (filterProp != null && filterProp.indexOf(value) >= 0) {
                    searchResults.push(child);
                }
                if (searchResults.length >= maxChildLength) {
                    overFlow = true;
                    break
                }
            }
        }
        setFilterResult({children: searchResults, overFlow});
        // const end = new Date().getTime();
        // console.log("耗时：" + (end - start) + "毫秒，循环" + count + "次");
    };

    const onSearch = useCallback(debounce(async (value) => {
        searchNow(value);
    }, debounceTime || 300, false), [props.optionFilterProp, children]);

    useEffect(() => {
        const childs = filterResult.children || [];
        const result = [...childs];
        if (props.value == null) {
            setShowChildren(result);
            return
        }

        const searchResultValues = childs.filter(c => c != null && c.props != null).map(s => s.props.value);
        if (typeof props.value === "string") {
            if (searchResultValues.indexOf(props.value) === -1) {
                result.push(childrenMap.current.get(props.value))
            }
        } else {
            props.value.forEach(v => {
                if (searchResultValues.indexOf(v) === -1) {
                    result.push(childrenMap.current.get(v))
                }
            });
        }
        setShowChildren(result);
    }, [props.value, filterResult]);

    useEffect(() => {
        const map = new Map();
        React.Children.forEach(children, (c, i) => {
            if (c != null && c.props != null) {
                map.set(c.props.value, c);
            }
        });
        childrenMap.current = map;
        searchNow(null);
    }, [children]);


    return (<Select {...rest}
                    filterOption={false}
                    onFocus={() => searchNow(null)}
                    onSearch={onSearch}>
        {showChildren.map((child) => (child))}
        {filterResult.overFlow ? toManyNotice : null}
    </Select>)
}
